home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Taifun
/
Taifun 048 (1988-02-15)(Ossowski, Stefan)(DE)(PD).zip
/
Taifun 048 (1988-02-15)(Ossowski, Stefan)(DE)(PD).adf
/
Mandel
/
source
/
gotmenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-23
|
23KB
|
811 lines
#define DEBUG
/* :ts=4
* M A N D E L B R O T C O N S T R U C T I O N S E T
*
* MenuPick and some related things
*/
#include <exec/types.h>
#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif
#include <intuition/intuition.h>
#ifdef DEBUG
# include <stdio.h>
# undef STATIC
# define STATIC /* EMPTY */
#endif
#include "mandel.h"
STATIC TEXT FileName[FNAME_SIZE+1] = "Mandel.pic";
STATIC TEXT DirName[DNAME_SIZE+2] = "df0:";
STATIC UBYTE Buffer[5][20];
/* Forward declarations of static procedures */
void PrjNew();
void GotMenu(Code)
USHORT Code;
{
static void (*MenuFunc[])()= {
CprMenu, PrjMenu, OptMenu, FunMenu };
while (Code != MENUNULL) {
(*MenuFunc[MENUNUM(Code)]) (Code);
Code = ItemAddress(MandelMenu, (long) Code) -> NextSelect;
/* This tends to make endless loops possible ... */
}
}
void CprMenu(Code)
USHORT Code;
{
ULONG OldIDCMP = MainWindow->IDCMPFlags;
static struct IntuiText Body[] =
{
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
10, 15, NULL, (UBYTE *)"Mandelbrot Construction Set", &Body[1] },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
10, 30, NULL, (UBYTE *)"By KosmoSoft Productions", &Body[2] },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
10, 40, NULL, (UBYTE *)"15 September 1987 V1.0", &Body[3] },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
10, 55, NULL, (UBYTE *)"Ohh, please Copy-Me!", NULL }
},
ExitText =
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
AUTOLEFTEDGE, AUTOTOPEDGE, NULL, (UBYTE *)" OK ", NULL };
ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY));
AutoRequest(MainWindow, &Body[0], NULL, &ExitText, NULL, NULL, 258L, 100L);
ModifyIDCMP(MainWindow, OldIDCMP);
}
STATIC void PrjMenu(Code)
USHORT Code;
{
int SubNum = SUBNUM(Code);
int ItemNum = ITEMNUM(Code);
struct Mand MandChunk;
struct BitMap *bitmap;
struct ILBM_info *ilbminfo;
unsigned char ea_colormap[3*MAXCOL];
char Name[DNAME_SIZE + FNAME_SIZE + 3];
switch (ItemNum) {
case PRJNEW: PrjNew(SubNum); break;
case PRJOPN:
if ( get_fname(MainWindow, "Select a filename to LOAD",
FileName, DirName) == NULL ) break;
strcpy(Name, DirName);
if (Name[strlen(Name) - 1] != ':') strcat(Name, "/");
strcat(Name, FileName);
StopDrawing();
MandChunk.MandID = 0;
if (ilbminfo = read_iff(Name,
(short)FALSE, sizeof(MandChunk), &MandChunk)) {
put_ea_cmap(&ilbminfo->cmap, NumColors, MandelScreen);
InterpretMAND(&MandChunk);
}
Saved = TRUE;
break;
case PRJSVE: /* Save */
if (NameValid) skipto prjsve;
/* Fall Through */
case PRJSVA: /* Save As */
if ( get_fname(MainWindow, "Select a filename to SAVE",
FileName, DirName) == NULL ) break;
prjsve:
strcpy(Name, DirName);
if (Name[strlen(Name) - 1] != ':') strcat(Name, "/");
strcat(Name, FileName);
get_ea_cmap(ea_colormap, NumColors, MandelScreen);
MakeMAND(&MandChunk);
bitmap = MainWindow->RPort->BitMap;
/*** Warning: This MoveWindow will not happen immediately!!! ***/
/*** For some reason, this will deadlock Intuition, if I ***/
/*** uncomment both MoveWindow and DoBorderless. It seems to ***/
/*** collide with the closing filename requester window... ***/
/*** Maybe because the locking of the layers interfere buggyly? ***/
/*** Anyhow, if I LockLayers(), then the GZZ border doesn't ***/
/*** get updated until I UnlockLayers(), and the mouse ***/
/*** pointer is frozen! But we have to suspend the drawing ***/
/*** task somehow, to prevent creating a corrupt IFF file. ***/
/*** Who said `Very near to betting that it can't be ***/
/*** deadlocked' ?? [allchanges file: intuition 290] ***/
/* MoveWindow(MainWindow, (long)-MainWindow->LeftEdge,
(long)-MainWindow->TopEdge); */
/* DoBorderless(MainWindow); */
SuspendDrawing();
NameValid = Saved = write_iff(Name, ea_colormap, bitmap,
(short) 0, (short) 0, (short) bitmap->BytesPerRow * 8,
(short) TRUE, sizeof(MandChunk), &MandChunk);
ResumeDrawing();
break;
case PRJQUI:
if (StillDrawing)
StopDrawing();
else
finished = TRUE;
}
}
STATIC void OptMenu(Code)
USHORT Code;
{
int SubNum = SUBNUM(Code);
int ItemNum = ITEMNUM(Code);
switch (ItemNum) {
case OPTCOL:
switch (SubNum) {
case OCSEL:
SelectMenu(MENU(OPTMENU, OPTCOL, OCSEL), (bool)FALSE);
UnImpl(); break;
case OCMOD:
PenTableMode = MODULO; break;
case OCRAN:
PenTableMode = RANGES; break;
case OCPAL:
Palette(MainWindow);
} /* End Switch SUBNUM */
InitPenTable();
break;
case OPTRES:
switch (SubNum) {
case ORNRM: PixelStep = 1; break;
case OR12: PixelStep = 2; break;
case OR13: PixelStep = 3; break;
case OR14: PixelStep = 4; break;
case ORFIL:
DrawPicture((bool)TRUE); break; /* Fill in */
case ORHI:
case ORILC:
if (!Sure()) break;
{
USHORT newmode = MandelNScreen.ViewModes & ~(HIRES | LACE);
bool WasBorderless;
if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, ORHI))
-> Flags & CHECKED)
newmode |= HIRES;
if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, ORILC))
-> Flags & CHECKED)
newmode |= LACE;
if (newmode != MandelNScreen.ViewModes) {
WasBorderless = CleanupDisplay((bool) TRUE);
MandelNScreen.ViewModes = newmode;
if (InitDisplay(WasBorderless)) { /* Trouble */
MandelNScreen.ViewModes &= ~(HIRES | LACE);
if (InitDisplay((bool) FALSE))
MyExit("Can't re-init display - Maybe low on memory");
SelectMenu(MENU(OPTMENU, OPTRES, ORHI), (bool)FALSE);
SelectMenu(MENU(OPTMENU, OPTRES, ORILC), (bool)FALSE);
SelectMenu(MENU(OPTMENU, OPTRES, ORBCK), (bool)FALSE);
}
}
}
break;
case ORBCK:
if (ItemAddress(MandelMenu, MENU(OPTMENU,OPTRES,ORBCK))->Flags & CHECKED)
DoBorderless(MainWindow, &borderinfo);
else
UndoBorderless(MainWindow, &borderinfo);
} /* End Switch SUBNUM */
break;
case OPTPAR: Parameters(); break;
} /* End Switch ITEMNUM */
}
void FunMenu(Code)
USHORT Code;
{
switch (ITEMNUM(Code)) {
case FUN1:
WritePixelDepth = ZQuadMinC; break;
case FUN2:
WritePixelDepth = ZC1MinZ; break;
case FUN3:
WritePixelDepth = Z3PlusZCMin1MinC; break;
}
}
void UnImpl()
{
static char alert[] = "\
\0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\
\0\170\40Sorry, this function has not been implemented yet!\0";
DisplayAlert(RECOVERY_ALERT, alert, 50L);
}
STATIC USHORT OldMinWidth, OldMinHeight, OldMaxWidth, OldMaxHeight;
/* Do not nest calls to DisableSizing: the original values will be lost. */
STATIC void DisableSizing()
{
OldMinWidth = MainWindow->MinWidth;
OldMaxWidth = MainWindow->MaxWidth;
OldMinHeight = MainWindow->MinHeight;
OldMaxHeight = MainWindow->MaxHeight;
WindowLimits(MainWindow, (long) MainWindow->Width, (long) MainWindow->Height,
(long) MainWindow->Width, (long) MainWindow->Height);
}
STATIC void EnableSizing()
{
WindowLimits(MainWindow, (long) OldMinWidth, (long) OldMinHeight,
(long) OldMaxWidth, (long) OldMaxHeight);
}
/* Complex multiplication using pointers to reduce overhead. */
/* YOU must make sure there are no (dynamic) aliases around... */
STATIC void MulCplx(ReRes, ImRes, ReA, ImA, ReB, ImB)
double *ReRes, *ImRes, *ReA, *ImA, *ReB, *ImB;
{
*ReRes = *ReA * *ReB - *ImA * *ImB;
*ImRes = *ImA * *ReB + *ReA * *ImB;
}
/* Z^2-C: 4 multiplications per loop */
void ZQuadMinC(x, y, ReC, ImC)
long x, y;
double ReC, ImC;
{
double ReZ = 0.0, ImZ = 0.0;
double ReQuad, ImQuad;
int Depth = -1;
while (ImQuad=ImZ*ImZ, ReQuad=ReZ*ReZ, Depth++,
(ImQuad + ReQuad < 8) && (Depth <= MaxDepth) )
{
ImZ = 2 * ImZ * ReZ - ImC;
ReZ = ReQuad - ImQuad - ReC;
}
if (Depth > MaxDepth)
Depth = PenTable[0];
else
Depth = PenTable[Depth];
SetAPen(MainWindow->RPort, (long) Depth);
WritePixel(MainWindow->RPort, x, y);
}
/* Z*C*(1-Z): 10 multiplications per loop */
void ZC1MinZ(x, y, ReC, ImC)
long x, y;
double ReC, ImC;
{
static double ReZ, ImZ;
static double NewReZ, NewImZ;
static double Re1MinZ, Im1MinZ;
int Depth = -1;
ReZ = ReC;
ImZ = ImC;
while (Depth++, (ImZ*ImZ + ReZ*ReZ < 8) && (Depth <= MaxDepth) )
{
Re1MinZ = 1 - ReZ;
Im1MinZ = -ImZ;
MulCplx(&NewReZ, &NewImZ, &ReZ, &ImZ, &ReC, &ImC);
MulCplx(&ReZ, &ImZ, &NewReZ, &NewImZ, &Re1MinZ, &Im1MinZ);
}
if (Depth > MaxDepth)
Depth = PenTable[0];
else
Depth = PenTable[Depth];
SetAPen(MainWindow->RPort, (long) Depth);
WritePixel(MainWindow->RPort, x, y);
}
/* Z^3+Z*(C-1)-C: 12 multiplications per loop */
void Z3PlusZCMin1MinC(x, y, ReC, ImC)
long x, y;
double ReC, ImC;
{
static double ReZ, ImZ;
static double ReCMin1;
static double ReZ2, ImZ2, ReZ3, ImZ3;
double ReQuad, ImQuad;
int Depth = -1;
ReZ = ReC;
ImZ = ImC;
while (ImQuad=ImZ*ImZ, ReQuad=ReZ*ReZ, Depth++,
(ImQuad + ReQuad < 8) && (Depth <= MaxDepth) )
{
/* Calculate z^2 */
ReZ2 = ReQuad - ImQuad;
ImZ2 = 2 * ReZ * ImZ;
/* Make z^3 */
MulCplx(&ReZ3, &ImZ3, &ReZ2, &ImZ2, &ReZ, &ImZ);
/* Calculate z(c-1) while destroying z^2 */
ReCMin1 = ReC - 1;
MulCplx(&ReZ2, &ImZ2, &ReZ, &ImZ, &ReCMin1, &ImC);
/* Add everything */
ReZ = ReZ3 + ReZ2 - ReC;
ImZ = ImZ3 + ImZ2 - ImC;
}
if (Depth > MaxDepth)
Depth = PenTable[0];
else
Depth = PenTable[Depth];
SetAPen(MainWindow->RPort, (long) Depth);
WritePixel(MainWindow->RPort, x, y);
}
/* Some *VERY PRIVATE* variables */
STATIC struct Task *DrawTask = NULL;
STATIC struct Task *MandelTask = NULL;
STATIC struct SignalSemaphore DrawSemaphore;
/* This is what it is all about! */
STATIC bool MyFillIn; /* Parameter for new task */
STATIC void ActuallyDrawPicture()
{
static double x, y, Leftx, MyXstep, MyYstep;
static long px, py, Leftpx, minpx, maxpx, minpy, maxpy;
static int MyPixelStep, XOffset, YOffset;
register void (*Function)();
geta4(); /* Manx small memory model */
ObtainSemaphore(&DrawSemaphore);
StillDrawing = TRUE;
DisableSizing();
StopFraming();
OffMenu(MainWindow, (ULONG) SHIFTMENU(PRJMENU) | SHIFTITEM(PRJNEW) |
SHIFTSUB(NOSUB) );
OffMenu(MainWindow, (ULONG) SHIFTMENU(OPTMENU) | SHIFTITEM(OPTRES) |
SHIFTSUB(ORFIL) );
if (!MyFillIn && !Sure()) skipto exit;
if (!MyFillIn) NameValid = FALSE;
Saved = FALSE;
MyPixelStep = PixelStep;
XOffset = 0;
YOffset = MyFillIn? 1: 0;
minpx = 0;
maxpx = MainWindow->GZZWidth - 1;
minpy = 0;
maxpy = MainWindow->GZZHeight - 1;
CalcCSteps();
if (!MyFillIn) { /* Clear the window */
SetAPen(MainWindow->RPort, (long) PenTable[0]);
SetDrMd(MainWindow->RPort, (long) JAM1);
RectFill(MainWindow->RPort, minpx, minpy, maxpx, maxpy);
}
MyXstep = MyPixelStep * CXStep;
MyYstep = MyPixelStep * CYStep;
Function = WritePixelDepth;
ReleaseSemaphore(&DrawSemaphore);
again:
Leftpx = minpx + XOffset; /* Start in the upper left-hand corner */
py = minpy + YOffset; /* of the window */
Leftx = LeftEdge + XOffset * CXStep;
y = TopEdge - YOffset * CYStep;
for ( ; py <= maxpy; y -= MyYstep, py += MyPixelStep) {
ObtainSemaphore(&DrawSemaphore);
SetDrMd(MainWindow->RPort, (long) JAM1);
for (px=Leftpx, x=Leftx ; px <= maxpx; x += MyXstep, px += MyPixelStep) {
(*Function)(px, py, x, y);
/* Check if we are asked to terminate. Don't release s'phore. */
if (StillDrawing < 0) skipto exit;
}
ReleaseSemaphore(&DrawSemaphore);
}
if (MyFillIn && (++YOffset < MyPixelStep) ) {
backto again; /* Draw pixels below current pixel */
}
if (MyFillIn && (++XOffset < MyPixelStep) ) {
YOffset = 0; /* and next to them */
backto again;
}
exit:
DisplayBeep(MandelScreen);
ObtainSemaphore(&DrawSemaphore);
EnableSizing();
OnMenu(MainWindow, (ULONG) SHIFTMENU(PRJMENU) | SHIFTITEM(PRJNEW) |
SHIFTSUB(NOSUB) );
OnMenu(MainWindow, (ULONG) SHIFTMENU(OPTMENU) | SHIFTITEM(OPTRES) |
SHIFTSUB(ORFIL) );
DrawTask = NULL;
if (StillDrawing < 0) {
/* Release the semaphore now. The main task waits for it. */
ReleaseSemaphore(&DrawSemaphore);
}
StillDrawing = FALSE; /* We are finished, finally... */
ReleaseSemaphore(&DrawSemaphore);
DisplayBeep(MandelScreen);
}
void DrawPicture(FillIn)
bool FillIn;
{
BYTE Priority;
MandelTask = FindTask(NULL);
Priority = MandelTask->tc_Node.ln_Pri;
MyFillIn = FillIn;
InitSemaphore(&DrawSemaphore);
DrawTask = CreateTask("Mandelbrot_Drawing.task", (long) Priority,
ActuallyDrawPicture, 2048L);
}
/* Interface because I wanted to CreateTask the drawing... */
void StopDrawing()
{
if (StillDrawing) {
StillDrawing = -1; /* Indicate termination is wanted. */
/* In worst-case I think we will make the loop at most twice. */
/* This is only when the drawing task has not obtained it, */
/* which is only for very little of the time. */
do {
ObtainSemaphore(&DrawSemaphore);
ReleaseSemaphore(&DrawSemaphore);
} while (StillDrawing < 0);
}
}
/* This is the external interface to the DrawSemaphore. Use it with care. */
/* Always balance calls to SuspendDrawing() with ResumeDrawing() !!! */
void SuspendDrawing()
{
ObtainSemaphore(&DrawSemaphore);
}
void ResumeDrawing()
{
ReleaseSemaphore(&DrawSemaphore);
}
STATIC void PrjNew(SubNum)
USHORT SubNum;
{
struct Window *window;
int ID;
static double HShift = 0.0,
VShift = 0.0;
double Width = RightEdge - LeftEdge,
Height = BottomEdge - TopEdge,
NewLeftEdge = LeftEdge,
NewTopEdge = TopEdge,
NewRightEdge = RightEdge,
NewBottomEdge = BottomEdge;
/* Stuff for the ABSOLUTE requester */
static struct IntuiText RatioText = {
MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 90, NULL,
(UBYTE *) "Ratio: ", NULL };
static struct IntuiText AbsText = {
MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
(UBYTE *) "Select an absolute position", &RatioText };
static struct IntuiText LRTBText[] = {
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
(UBYTE *) "Left", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
(UBYTE *) "Right", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
(UBYTE *) "Top", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
(UBYTE *) "Bottom", NULL }
};
static struct StringInfo LRTBinfo[] = {
{ &Buffer[0][0], &Buffer[4][0], 0, 20, 0 },
{ &Buffer[1][0], &Buffer[4][0], 0, 20, 0 },
{ &Buffer[2][0], &Buffer[4][0], 0, 20, 0 },
{ &Buffer[3][0], &Buffer[4][0], 0, 20, 0 }
};
static struct Gadget LRTBGadget[] = {
{ &LRTBGadget[1], 66, 30, 160, 10, /* next, LTWH */
GADGHCOMP, /* Flags */
RELVERIFY, /* Activation */
STRGADGET | REQGADGET, /* GadgetType */
(APTR) NULL, NULL, /* rendering */
&LRTBText[0], 0, (APTR) &LRTBinfo[0], /* "Left" */
NEGGADGETID+1, NULL },
{ &LRTBGadget[2], 66, 45, 160, 10, /* next, LTWH */
GADGHCOMP,
RELVERIFY,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&LRTBText[1], 0, (APTR) &LRTBinfo[1], /* Right */
NEGGADGETID+1, NULL },
{ &LRTBGadget[3], 66, 60, 160, 10, /* next, LTWH */
GADGHCOMP,
RELVERIFY,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&LRTBText[2], 0, (APTR) &LRTBinfo[2], /* Top */
NEGGADGETID+1, NULL },
{ NULL, 66, 75, 160, 10, /* next, LTWH */
GADGHCOMP,
RELVERIFY,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&LRTBText[3], 0, (APTR) &LRTBinfo[3], /* Bottom */
NEGGADGETID+1, NULL }
};
static struct Requester AbsRequest = {
NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
&AbsText, 0, 1 };
/* Stuff for the SHIFT requester */
static struct IntuiText ShiftText = {
MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
(UBYTE *) "Select a window shift amount", NULL };
static struct IntuiText RDText[] = {
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
(UBYTE *) "Right", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
(UBYTE *) "Down", NULL }
};
static struct Gadget RDGadget[] = {
{ &RDGadget[1], 66, 45, 160, 10, /* next, LTWH */
GADGHCOMP,
0,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&RDText[0], 0, (APTR) &LRTBinfo[0], /* Right */
0, NULL },
{ NULL, 66, 60, 160, 10, /* next, LTWH */
GADGHCOMP,
0,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&RDText[1], 0, (APTR) &LRTBinfo[1], /* Down */
0, NULL }
};
static struct Requester ShiftRequest = {
NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
&ShiftText, 0, 1 };
switch (SubNum) {
case PNRED:
if (MouseStatus != FLASHING) return;
else {
register SHORT w = MainWindow -> GZZWidth,
h = MainWindow -> GZZHeight;
register SHORT X1, Y1, X2, Y2;
/* If you cast less, Aztec seems to do it wrong... */
X1 = (-(long)FrameX1 * w) / ((long)FrameX2 - (long)FrameX1);
Y1 = (-(long)FrameY1 * h) / ((long)FrameY2 - (long)FrameY1);
X2 = ((long)(w-1-FrameX1) * w) / ((long)FrameX2 - (long)FrameX1)
- 1;
Y2 = ((long)(h-1-FrameY1) * h) / ((long)FrameY2 - (long)FrameY1)
- 1;
#ifdef DEBUG2
fprintf(stderr,"REDUCE: w=%d h=%d X1=%d Y1=%d X2=%d Y2=%d\n",
w, h, X1, Y1, X2, Y2);
fprintf(stderr," FrameX1=%d FrameY1=%d FrameX2=%d FrameY2=%d\n",
FrameX1, FrameY1, FrameX2, FrameY2);
#endif
NewLeftEdge = LeftEdge + X1 * CXStep;
NewRightEdge = LeftEdge + X2 * CXStep;
NewTopEdge = TopEdge - Y1 * CYStep;
NewBottomEdge = TopEdge - Y2 * CYStep;
skipto pnabs;
}
case PNENL:
if (MouseStatus != FLASHING) return;
NewLeftEdge = LeftEdge + FrameX1 * CXStep;
NewRightEdge = LeftEdge + FrameX2 * CXStep;
NewTopEdge = TopEdge - FrameY1 * CYStep;
NewBottomEdge = TopEdge - FrameY2 * CYStep;
skipto pnabs;
case PNSHF:
NegativeGadget.NextGadget = &RDGadget[0];
do {
sprintf(Buffer[0], "%1.6g",HShift);
sprintf(Buffer[1], "%1.6g",VShift);
window = MyRequest(&ShiftRequest, MainWindow);
ID = WaitMyRequest(window);
EndMyRequest(&ShiftRequest, window, MainWindow);
if (ID == NEGGADGETID) return;
} while (sscanf(Buffer[0], "%lf", &HShift)+
sscanf(Buffer[1], "%lf", &VShift) != 2);
NewLeftEdge = LeftEdge + HShift * Width;
NewRightEdge = RightEdge + HShift * Width;
NewTopEdge = TopEdge + VShift * Height;
NewBottomEdge = BottomEdge + VShift * Height;
skipto pnabs;
case PNABS:
NewLeftEdge = LeftEdge;
NewRightEdge = RightEdge;
NewTopEdge = TopEdge;
NewBottomEdge = BottomEdge;
pnabs:
NegativeGadget.NextGadget = &LRTBGadget[0];
sprintf(Buffer[0], "%1.10g", NewLeftEdge);
sprintf(Buffer[1], "%1.10g", NewRightEdge);
sprintf(Buffer[2], "%1.10g", NewTopEdge);
sprintf(Buffer[3], "%1.10g", NewBottomEdge);
sprintf(RatioText.IText+7, "%1.4f ", Ratio(NewLeftEdge,
NewRightEdge, NewTopEdge, NewBottomEdge, MainWindow));
do {
window = MyRequest(&AbsRequest, MainWindow);
while ( (ID = WaitMyRequest(window) ) > NEGGADGETID) {
sscanf(Buffer[0], "%lf", &NewLeftEdge);
sscanf(Buffer[1], "%lf", &NewRightEdge);
sscanf(Buffer[2], "%lf", &NewTopEdge);
sscanf(Buffer[3], "%lf", &NewBottomEdge);
sprintf(RatioText.IText+7, "%1.4f ",
Ratio(NewLeftEdge, NewRightEdge, NewTopEdge,
NewBottomEdge, MainWindow));
PrintIText(AbsRequest.ReqLayer->rp, &RatioText, 0L, 0L);
}
EndMyRequest(&AbsRequest, window, MainWindow);
} while (sscanf(Buffer[0], "%lf", &NewLeftEdge)+
sscanf(Buffer[1], "%lf", &NewRightEdge)+
sscanf(Buffer[2], "%lf", &NewTopEdge)+
sscanf(Buffer[3], "%lf", &NewBottomEdge) < 4);
if (ID != POSGADGETID) return;
LeftEdge = NewLeftEdge;
RightEdge = NewRightEdge;
TopEdge = NewTopEdge;
BottomEdge = NewBottomEdge;
StopFraming();
StopDrawing();
break;
}
DrawPicture((bool)FALSE); /* Don't fill in */
}
float Ratio(l, r, t, b, window)
double l, r, t, b;
struct Window *window;
{
float PixelRatio;
float ReImRatio;
if (t == b) t = b+1; /* You never know... */
PixelRatio = (float) window->GZZWidth / window->GZZHeight;
if (window->WScreen->ViewPort.Modes & HIRES) PixelRatio /= 2;
if (window->WScreen->ViewPort.Modes & LACE) PixelRatio *= 2;
ReImRatio = (r - l)/(t - b);
return ReImRatio / PixelRatio;
}
void Parameters()
{
struct Window *window;
int ID;
int NewMaxDepth, NewRangeWidth;
static struct IntuiText ParamText = {
MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
(UBYTE *) "Select these parameters", NULL };
static struct IntuiText ParmText[] = {
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
(UBYTE *) "Max depth", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
(UBYTE *) "Range width", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
(UBYTE *) "", NULL },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
(UBYTE *) "", NULL }
};
static struct StringInfo Parminfo[] = {
{ &Buffer[0][0], &Buffer[4][0], 0, 20, 0 },
{ &Buffer[1][0], &Buffer[4][0], 0, 20, 0 },
{ &Buffer[2][0], &Buffer[4][0], 0, 20, 0 },
{ &Buffer[3][0], &Buffer[4][0], 0, 20, 0 }
};
static struct Gadget ParmGadget[] = {
{ &ParmGadget[1], 130, 30, 96, 10, /* next, LTWH */
GADGHCOMP, /* Flags */
RELVERIFY | LONGINT, /* Activation */
STRGADGET | REQGADGET, /* GadgetType */
(APTR) NULL, NULL, /* rendering */
&ParmText[0], 0, (APTR) &Parminfo[0], /* "MaxDepth" */
0, NULL },
{ &ParmGadget[2], 130, 45, 96, 10, /* next, LTWH */
GADGHCOMP,
RELVERIFY | LONGINT,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&ParmText[1], 0, (APTR) &Parminfo[1], /* "RangeWidth" */
0, NULL },
{ &ParmGadget[3], 130, 60, 96, 10, /* next, LTWH */
GADGHCOMP,
RELVERIFY,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&ParmText[2], 0, (APTR) &Parminfo[2], /* */
0, NULL },
{ NULL, 130, 75, 96, 10, /* next, LTWH */
GADGHCOMP,
RELVERIFY,
STRGADGET | REQGADGET,
(APTR) NULL, NULL,
&ParmText[3], 0, (APTR) &Parminfo[3], /* */
0, NULL }
};
static struct Requester ParmRequest = {
NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
&ParamText, 0, 1 };
/* Stuff for the PARAMETERS requester */
NegativeGadget.NextGadget = &ParmGadget[0];
Parminfo[0].LongInt = MaxDepth;
Parminfo[1].LongInt = RangeWidth;
do {
sprintf(Buffer[0], "%ld", Parminfo[0].LongInt);
sprintf(Buffer[1], "%ld", Parminfo[1].LongInt);
Buffer[2][0] = Buffer[3][0] = '\0';
window = MyRequest(&ParmRequest, MainWindow);
ID = WaitMyRequest(window);
EndMyRequest(&ParmRequest, window, MainWindow);
if (ID == NEGGADGETID) return;
NewMaxDepth = Parminfo[0].LongInt;
NewRangeWidth = Parminfo[1].LongInt;
} while ( NewMaxDepth < 0 || NewMaxDepth > MAXDEPTH ||
NewRangeWidth < 0 || NewRangeWidth > MAXDEPTH );
if (NewRangeWidth != RangeWidth) InitPenTable();
MaxDepth = NewMaxDepth;
RangeWidth = NewRangeWidth;
}